home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / m4-1_0_3.lha / m4-1.0.3 / m4.c < prev    next >
C/C++ Source or Header  |  1992-12-19  |  13KB  |  600 lines

  1. /*
  2.  * GNU m4 -- A simple macro processor
  3.  * Copyright (C) 1989-1992 Free Software Foundation, Inc.
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2, or (at your option)
  8.  * any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19.  
  20. #include "m4.h"
  21. #include "getopt.h"
  22. #include <sys/types.h>
  23. #include <sys/signal.h>
  24.  
  25. static void cmd_error ();
  26.  
  27.  
  28. /* Current version numbers.  */
  29. static const char version[] = "1.0.3";
  30.  
  31. /* Operate interactively (-e).  */
  32. static int interactive = 0;
  33.  
  34. /* Enable sync output for /lib/cpp (-s).  */
  35. int sync_output = 0;
  36.  
  37. /* Debug (-d[flags]).  */
  38. int debug_level = 0;
  39.  
  40. /* Hash table size (should be a prime) (-Hsize).  */
  41. int hash_table_size = HASHMAX;
  42.  
  43. /* Number of diversions allocated.  */
  44. int ndiversion = NDIVERSIONS;
  45.  
  46. /* Disable GNU extensions (-G).  */
  47. int no_gnu_extensions = 0;
  48.  
  49. /* Max length of arguments in trace output (-lsize).  */
  50. int max_debug_argument_length = 0;
  51.  
  52. /* Suppress warnings about missing arguments.  */
  53. int suppress_warnings = 0;
  54.  
  55. /* Program name.  */
  56. const char *progname = NULL;
  57.  
  58. static struct option const m4_options[] =
  59. {
  60.   { "interactive",        no_argument,        NULL, 'e' },
  61.   { "version",            no_argument,        NULL, 'V' },
  62.   { "synclines",        no_argument,        NULL, 's' },
  63.   { "debug",            optional_argument,    NULL, 'd' },
  64.   { "arglength",        required_argument,    NULL, 'l' },
  65.   { "erroroutput",        required_argument,    NULL, 'o' },
  66.   { "hashsize",            required_argument,    NULL, 'H' },
  67.   { "diversions",        required_argument,    NULL, 'N' },
  68.   { "include",            required_argument,    NULL, 'I' },
  69.   { "no-gnu-extensions",    no_argument,        NULL, 'G' },
  70.   { "silent",            no_argument,        NULL, 'Q' },
  71.   { "quiet",            no_argument,        NULL, 'Q' },
  72.  
  73.   /* These are somewhat troublesome.  */
  74.   { "define",            required_argument,    NULL, 'D' },
  75.   { "undefine",            required_argument,    NULL, 'U' },
  76.   { "trace",            required_argument,    NULL, 't' },
  77.   { NULL },
  78. };
  79.  
  80. #define OPTSTRING "esGQVD:U:t:B:H:o:l:d::S:T:I:N:"
  81.  
  82. struct macro_definition
  83. {
  84.   struct macro_definition *next;
  85.   int code;            /* D, U or t */
  86.   char *macro;
  87. };
  88. typedef struct macro_definition macro_definition;
  89.  
  90.  
  91. /*
  92.  * usage --- Print usage message on stderr.
  93.  */
  94. static void
  95. usage (void)
  96. {
  97.   fprintf (stderr, "\
  98. Usage: m4 [OPTION]... [FILE]...\n\
  99. \n\
  100.   -D, --define NAME[=VALUE]     enter NAME has having VALUE, or empty\n\
  101.   -G, --no-gnu-extensions       suppress all GNU extensions\n\
  102.   -H, --hashsize PRIME          set symbol lookup hash table size\n\
  103.   -I, --include DIRECTORY       search this directory second for includes\n\
  104.   -N, --diversions NUMBER       select number of simultaneous diversions\n\
  105.   -Q, --quiet, --silent         suppress some warnings for builtins\n\
  106.   -U, --undefine NAME           delete builtin NAME\n\
  107.   -V, --version                 print version number\n\
  108.   -d, --debug [FLAGS]           set debug level\n\
  109.   -e, --interactive             unbuffer output, ignore interrupts\n\
  110.   -l, --arglength NUM           restrict macro tracing size\n\
  111.   -o, --erroroutput FILE        redirect debug and trace output\n\
  112.   -s, --synclines               generate `#line NO \"FILE\"' lines\n\
  113.   -t, --trace NAME              trace NAME when it will be defined\n\
  114. \n\
  115. If no FILE or if FILE is `-', standard input is read.\n");
  116. #ifdef IMPLEMENT_M4OPTS
  117.   fprintf (stderr, "\
  118. Options can be given through M4OPTS environment variable.\n");
  119. #endif
  120.  
  121.   exit (1);
  122. }
  123.  
  124. #ifdef IMPLEMENT_M4OPTS
  125. /*
  126.  * Split a string of arguments in ENV, taken from the environment.
  127.  * Return generated argv, and the number through the pointer ARGCP.
  128.  */
  129. static char **
  130. split_env_args (char *env, int *argcp)
  131. {
  132.   char **argv;
  133.   int argc;
  134.  
  135.   if (env == NULL)
  136.     {
  137.       *argcp = 0;
  138.       return NULL;
  139.     }
  140.  
  141.   /* This should be enough.  */
  142.   argv = (char **) xmalloc ((strlen (env) / 2 + 3) * sizeof (char *));
  143.  
  144.   argc = 1;
  145.   for (;;)
  146.     {
  147.       while (*env && (*env == ' ' || *env == '\t' || *env == '\n'))
  148.     env++;
  149.  
  150.       if (*env == '\0')
  151.     break;
  152.  
  153.       argv[argc++] = env;
  154.  
  155.       while (*env && !(*env == ' ' || *env == '\t' || *env == '\n'))
  156.     env++;
  157.  
  158.       if (*env == '\0')
  159.     break;
  160.  
  161.       *env++ = '\0';
  162.     }
  163.   argv[argc] = NULL;
  164.  
  165.   *argcp = argc;
  166.   return argv;
  167. }
  168. #endif /* IMPLEMENT_M4OPTS */
  169.  
  170.  
  171. /*
  172.  * Parse the arguments ARGV.  Arguments that cannot be handled until
  173.  * later (i.e., -D, -U and -t) are accumulated on a list, which is
  174.  * returned through DEFINES.  The function returns the rest of the
  175.  * arguments.
  176.  */
  177. #ifndef IMPLEMENT_M4OPTS
  178. static const char **
  179. parse_args (int argc, const char **argv, macro_definition **defines)
  180. #else /* IMPLEMENT_M4OPTS */
  181. static const char **
  182. parse_args (int cmdargc, const char **cmdargv, macro_definition **defines)
  183. #endif /* IMPLEMENT_M4OPTS */
  184. {
  185.   int option;            /* option character */
  186.   int dummy;            /* dummy option_index, unused */
  187.   boolean print_version;    /* print version before return */
  188. #ifdef IMPLEMENT_M4OPTS
  189.   const char **argv;        /* argv from environment M4OPTS */
  190.   int argc;            /* argc fron environment M4OPTS */
  191. #endif
  192.   macro_definition *head;    /* head of deferred argument list */
  193.   macro_definition *tail;
  194.   macro_definition *new;
  195.  
  196.   head = tail = NULL;
  197.   print_version = FALSE;
  198.  
  199. #ifdef IMPLEMENT_M4OPTS
  200.   /* Should find a way to avoid the cast.  */
  201.   argv = (const char **) split_env_args (getenv ("M4OPTS"), &argc);
  202.   if (argv == NULL)
  203.     {
  204.       argv = cmdargv;
  205.       argc = cmdargc;
  206.       cmdargv = NULL;
  207.     }
  208. #endif /* IMPLEMENT_M4OPTS */
  209.  
  210.   while (TRUE)
  211.     {
  212.       /* Should find a way to avoid the cast.  */
  213.       option = getopt_long (argc, (char *const *) argv,
  214.                 OPTSTRING, m4_options, &dummy);
  215.  
  216. #ifndef IMPLEMENT_M4OPTS
  217.       if (option == EOF)
  218.     break;
  219. #else /* IMPLEMENT_M4OPTS */
  220.  
  221.       /* Setting M4OPTS will likely break shell scripts that use m4 and
  222.      don't expect options that they don't give it to be set.  That's
  223.      why in general, noninteractive utilities shouldn't take options
  224.      from environment variables.  For programs like less and vi, it's
  225.      ok because the environment variables usually just affect the
  226.      appearance of what the user sees.  David Mackenzie, 1992-03-10.  */
  227.  
  228.       if (option == EOF)
  229.     {
  230.       if (cmdargv != NULL)
  231.         {
  232.           if (optind != argc)
  233.         cmd_error ("warning: excess file arguments in M4OPTS ignored");
  234.  
  235.           argv = cmdargv;
  236.           argc = cmdargc;
  237.           cmdargv = NULL;
  238.           optind = 0;
  239.           continue;
  240.         }
  241.       else
  242.         break;
  243.     }
  244. #endif /* IMPLEMENT_M4OPTS */      
  245.  
  246.       switch (option)
  247.     {
  248.     case 'e':
  249.       interactive = 1;
  250.       break;
  251.  
  252.     case 's':
  253.       sync_output = 1;
  254.       break;
  255.  
  256.     case 'G':
  257.       no_gnu_extensions = 1;
  258.       break;
  259.  
  260.     case 'Q':
  261.       suppress_warnings = 1;
  262.       break;
  263.  
  264.     case 'V':
  265.       print_version = TRUE;
  266.       break;
  267.  
  268.     case 'd':
  269.       debug_level = debug_decode (optarg);
  270.       if (debug_level < 0)
  271.         {
  272.           cmd_error ("bad debug flags: `%s'", optarg);
  273.           debug_level = 0;
  274.         }
  275.       break;
  276.  
  277.     case 'l':
  278.       max_debug_argument_length = atoi (optarg);
  279.       if (max_debug_argument_length <= 0)
  280.         max_debug_argument_length = 0;
  281.       break;
  282.  
  283.     case 'o':
  284.       if (!debug_set_output (optarg))
  285.         cmd_error ("cannot set error file %s: %s", optarg, syserr ());
  286.       break;
  287.  
  288.     case 'H':
  289.       hash_table_size = atoi (optarg);
  290.       if (hash_table_size <= 0)
  291.         hash_table_size = HASHMAX;
  292.       break;
  293.  
  294.     case 'N':
  295.       ndiversion = atoi (optarg);
  296.       if (ndiversion <= 0)
  297.         ndiversion = NDIVERSIONS;
  298.       break;
  299.  
  300.     case 'I':
  301.       add_include_directory (optarg);
  302.       break;
  303.  
  304.     case 'B':        /* compatibility junk */
  305.     case 'S':
  306.     case 'T':
  307.       break;
  308.  
  309.     case 'D':
  310.     case 'U':
  311.     case 't':
  312.       new = (macro_definition *) xmalloc (sizeof (macro_definition));
  313.       new->code = option;
  314.       new->macro = optarg;
  315.       new->next = NULL;
  316.  
  317.       if (head == NULL)
  318.         head = new;
  319.       else
  320.         tail->next = new;
  321.       tail = new;
  322.  
  323.       break;
  324.  
  325.     default:
  326.       usage ();
  327.     }
  328.     }
  329.  
  330.   if (print_version)
  331.     fprintf (stderr, "\
  332. GNU m4 %s, Copyright (C) 1989-1992 Free Software Foundation, Inc.\n\
  333. There is ABSOLUTELY NO WARRANTY for GNU m4.  See the file\n\
  334. COPYING in the source distribution for more details.\n",
  335.         version);
  336.  
  337.   *defines = head;
  338.   return argv + optind;
  339. }
  340.  
  341.  
  342. int
  343. main (int argc, const char **argv)
  344. {
  345.   macro_definition *defines;
  346.   FILE *fp;
  347.  
  348.   progname = rindex (argv[0], '/');
  349.   if (progname == NULL)
  350.     progname = argv[0];
  351.   else
  352.     progname++;
  353.  
  354.   include_init ();
  355.   debug_init ();
  356.  
  357.   /*
  358.    * First, we decode the arguments, to size up tables and stuff.
  359.    */
  360.   argv = parse_args (argc, argv, &defines);
  361.  
  362.   /*
  363.    * Do the basic initialisations.
  364.    */
  365.   input_init ();
  366.   output_init ();
  367.   symtab_init ();
  368.   builtin_init ();
  369.   include_env_init ();
  370.  
  371.   /*
  372.    * Handle deferred command line macro definitions.  Must come after
  373.    * initialisation of the symbol table.
  374.    */
  375.   while (defines != NULL)
  376.     {
  377.       macro_definition *next;
  378.       char *macro_value;
  379.       symbol *sym;
  380.  
  381.       switch (defines->code)
  382.     {
  383.     case 'D':
  384.       macro_value = index (defines->macro, '=');
  385.       if (macro_value == NULL)
  386.         macro_value = "";
  387.       else
  388.         *macro_value++ = '\0';
  389.       define_user_macro (defines->macro, macro_value, SYMBOL_INSERT);
  390.       break;
  391.  
  392.     case 'U':
  393.       lookup_symbol (defines->macro, SYMBOL_DELETE);
  394.       break;
  395.  
  396.     case 't':
  397.       sym = lookup_symbol (defines->macro, SYMBOL_INSERT);
  398.       SYMBOL_TRACED (sym) = TRUE;
  399.       break;
  400.  
  401.     default:
  402.       internal_error ("bad code in deferred arguments.");
  403.     }
  404.  
  405.       next = defines->next;
  406.       xfree (defines);
  407.       defines = next;
  408.     }
  409.  
  410.   /*
  411.    * Interactive mode means unbuffered output, and interrupts ignored.
  412.    */
  413.   if (interactive)
  414.     {
  415.       signal (SIGINT, SIG_IGN);
  416.       setbuf (stdout, (char *) NULL);
  417.     }
  418.  
  419.   /*
  420.    * Handle the various input files.  Each file is pushed on the
  421.    * input, and the input read.  Wrapup text is handled separately
  422.    * later.
  423.    */
  424.   if (*argv == NULL)
  425.     {
  426.       push_file (stdin, "stdin");
  427.       expand_input ();
  428.     }
  429.   else
  430.     for (; *argv != NULL; argv++)
  431.       {
  432.     if (strcmp (*argv, "-") == 0)
  433.       {
  434.         push_file (stdin, "stdin");
  435.       }
  436.     else
  437.       {
  438.         fp = path_search (*argv);
  439.         if (fp == NULL)
  440.           {
  441.         cmd_error ("can't open %s: %s", *argv, syserr ());
  442.         continue;
  443.           }
  444.         else
  445.           push_file (fp, *argv);
  446.       }
  447.     expand_input ();
  448.       }
  449. #undef NEXTARG
  450.  
  451.   /* Now handle wrapup text.  */
  452.   while (pop_wrapup ())
  453.     expand_input ();
  454.  
  455.   undivert_all ();
  456.  
  457.   return 0;
  458. }
  459.  
  460.  
  461. /*
  462.  * The rest of this file contains error handling functions, and memory
  463.  * allocation.
  464.  */
  465.  
  466. /* Non m4 specific error -- just complain.  */
  467. /* VARARGS */
  468. static void
  469. cmd_error (va_alist)
  470.     va_dcl
  471. {
  472.   va_list args;
  473.   char *fmt;
  474.  
  475.   fprintf (stderr, "%s: ", progname);
  476.  
  477.   va_start (args);
  478.   fmt = va_arg (args, char *);
  479.   vfprintf (stderr, fmt, args);
  480.   va_end (args);
  481.  
  482.   putc ('\n', stderr);
  483. }
  484.  
  485. /* Basic varargs function for all error output.  */
  486. static void
  487. vmesg (char *level, va_list args)
  488. {
  489.   char *fmt;
  490.  
  491.   fflush (stdout);
  492.   fmt = va_arg (args, char *);
  493.   fprintf (stderr, "%s:%s:%d: ", progname, current_file, current_line);
  494.   if (level != NULL)
  495.     fprintf (stderr, "%s: ", level);
  496.   vfprintf (stderr, fmt, args);
  497.   putc ('\n', stderr);
  498. }
  499.  
  500. /* Internal errors -- print and dump core.  */
  501. /* VARARGS */
  502. volatile void
  503. internal_error (va_alist)
  504.     va_dcl
  505. {
  506.   va_list args;
  507.   va_start (args);
  508.   vmesg ("internal error", args);
  509.   va_end (args);
  510.  
  511.   abort ();
  512. }
  513.  
  514. /* Fatal error -- print and exit.  */
  515. /* VARARGS */
  516. volatile void
  517. fatal (va_alist)
  518.     va_dcl
  519. {
  520.   va_list args;
  521.   va_start (args);
  522.   vmesg ("fatal error", args);
  523.   va_end (args);
  524.  
  525.   exit (1);
  526. }
  527.  
  528. /* "Normal" error -- just complain.  */
  529. /* VARARGS */
  530. void
  531. error (va_alist)
  532.     va_dcl
  533. {
  534.   va_list args;
  535.   va_start (args);
  536.   vmesg ((char *) NULL, args);
  537.   va_end (args);
  538. }
  539.  
  540. /* Warning --- for potential trouble.  */
  541. /* VARARGS */
  542. void
  543. warning (va_alist)
  544.     va_dcl
  545. {
  546.   va_list args;
  547.   va_start (args);
  548.   vmesg ("warning", args);
  549.   va_end (args);
  550. }
  551.  
  552.  
  553. /*
  554.  * Memory allocation functions
  555.  */
  556.  
  557. /* Out of memory error -- die.  */
  558. static void
  559. no_memory (void)
  560. {
  561.   fatal ("Out of memory");
  562. }
  563.  
  564. /* Free previously allocated memory.  */
  565. void
  566. xfree (void *p)
  567. {
  568.   if (p != NULL)
  569.     free (p);
  570. }
  571.  
  572. /* Semi-safe malloc -- never returns NULL.  */
  573. void *
  574. xmalloc (unsigned int size)
  575. {
  576.   register void *cp = malloc (size);
  577.   if (cp == NULL)
  578.     no_memory ();
  579.   return cp;
  580. }
  581.  
  582. #if 0
  583. /* Ditto realloc.  */
  584. void *
  585. xrealloc (void *p, unsigned int size)
  586. {
  587.   register void *cp = realloc (p, size);
  588.   if (cp == NULL)
  589.     no_memory ();
  590.   return cp;
  591. }
  592. #endif
  593.  
  594. /* And strdup.  */
  595. char *
  596. xstrdup (const char *s)
  597. {
  598.   return strcpy (xmalloc ((unsigned int) strlen (s) + 1), s);
  599. }
  600.